package com.xunyi.learndemo.queue;

import com.xunyi.learndemo.domain.OrderInfo;
import com.xunyi.learndemo.service.IOrderInfoService;
import com.xunyi.learndemo.service.OrderService;
import org.springframework.boot.CommandLineRunner;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Date;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.Executors;

@Component
public class OrderDelayManager implements CommandLineRunner {

    @Resource
    private IOrderInfoService orderInfoService;

    private DelayQueue<OrderDelayTask> delayQueue = new DelayQueue<>();

    //30分钟
    public static final long ORDER_TIMEOUT = 30 * 60 * 1000;

    public void addQueue(OrderInfo order) {
        delayQueue.put(new OrderDelayTask(order, ORDER_TIMEOUT));
    }

    @Scheduled(fixedRate = 1000)  // 每秒执行一次
    public void mockOrder() {
        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setOrderNum(String.valueOf(System.currentTimeMillis()));
        orderInfo.setCreateTime(new Date());
        orderInfo.setOrderStatus("UNPAID");
        addQueue(orderInfo);
    }

    // 任务消费线程
    public void processDelayedOrders() {
        while (true) {
            try {
                OrderDelayTask task = delayQueue.take();
                this.processOrder(task);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }

    public void processOrder(OrderDelayTask task) {
        System.out.println("开始处理超时任务：" + task.getOrder().getOrderNum());
        OrderInfo order = task.getOrder();
        if (order.getOrderStatus().equals(OrderService.OrderStatus.UNPAID.name())) {
            order.setOrderStatus(OrderService.OrderStatus.CANCELED.name());
            orderInfoService.updateOrderInfo(order);
        }
    }

    @Override
    public void run(String... args) throws Exception {
        //初始化延时任务消费线程
        Executors.newSingleThreadExecutor().execute(new Thread(this::processDelayedOrders));
    }
}
